Comencemos cargando los paquetes iniciales
library("dplyr")
library("tm.plugin.webmining")
library("purrr")
library("tidytext")
library("gutenbergr")
library("ggplot2")En esta ocasión estaremos usando el paquete gutenbergr que nos permite descargar los libros del Proyecto Gutenberg. Para obtener el ID del libro podemos ingresar a la página del Proyecto Gutenberg desarrollado por David Robinson
Separamos las líneas de texto en palabras y quitamos las palabras vacías
#filtramos palabras con 3 o menos letras
odisea_ordenada %>%
count(word, sort = TRUE) %>%
filter(n > 135,
!nchar(as.character(word)) <= 3) %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n), color = n) +
geom_col() +
xlab(NULL) +
coord_flip() +
labs(title = "Las palabras más frecuentes en La Odisea",
y = "Cantidad de palabras")Existen algunos diccionarios que podemos usar en R para obtener sentimientos de palabras. En esta sección debemos elegir el método que se adapte mejor a nuestro texto objetivo y tenga relación con lo que queremos obtener de él.
Para eso necesitamos observar qué hacen exactamente cada uno de ellos.
Este método puede clasificar 1620 palabras del libro entre sentimiento “positivo” y “negativo”
sentimientos_bing <- odisea_ordenada %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
ungroup()
sentimientos_bingsentimientos_bing %>%
group_by(sentiment) %>%
top_n(10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(y = "Contribución de sentimiento por palabra",
x = NULL) +
coord_flip()odiseanrc1 %>%
group_by(sentiment) %>%
top_n(10) %>%
ungroup() %>%
mutate(word = reorder(word, n)) %>%
ggplot(aes(word, n, fill = sentiment)) +
geom_col(show.legend = FALSE) +
facet_wrap(~sentiment, scales = "free_y") +
labs(y = "Contribución de sentimiento por palabra",
x = NULL) +
coord_flip()valorafinn <- as.numeric(odiseaafinn$value)
suavizado_afinn <- tibble(Palabras = 1:length(valorafinn),
Sentimiento = scales::rescale(valorafinn)) %>%
ggplot(aes(Palabras, Sentimiento)) +
geom_smooth(se = FALSE) +
theme_bw() +
ggtitle("suavizado de tendencia GAM")
suavizado_afinnlibrary(wordcloud)
odisea_ordenada %>%
anti_join(stop_words) %>%
count(word) %>%
with(wordcloud(word, n, max.words = 100))library(reshape2)
odisea_ordenada %>%
inner_join(get_sentiments("bing")) %>%
count(word, sentiment, sort = TRUE) %>%
acast(word ~ sentiment, value.var = "n", fill = 0) %>% as.data.frame() %>%
rename(Negativas = negative,
Positivas = positive) %>%
comparison.cloud(colors = c("#F8766D", "#00BFC4"),
max.words = 100)odisea_bigramas <- odisea %>%
unnest_tokens(bigram, text, token = "ngrams", n = 2) %>% rename(bigrama = bigram)
odisea_bigramaslibrary(tidyr)
bigramas_separados <- odisea_bigramas %>%
separate(bigrama, c("palabra1", "palabra2"), sep = " ")
bigramas_filtrados <- bigramas_separados %>%
filter(!palabra1 %in% stop_words$word) %>%
filter(!palabra2 %in% stop_words$word)
conteo_bigramas <- bigramas_filtrados %>%
count(palabra1, palabra2, sort = TRUE)
conteo_bigramasbigramas_unidos <- bigramas_filtrados %>%
unite(bigrama, palabra1, palabra2, sep = " ")
bigramas_unidosMostramos el conteo de los bigramas
library(viridis)
conteo_bigramas_unidos <- bigramas_unidos %>%
count(bigrama,sort = T)
conteo_bigramas_unidos <- conteo_bigramas_unidos %>% filter(n>10)
conteo_bigramas_unidosRelaciones entre bigramas
library(igraph)
grafica_bigrama <- conteo_bigramas %>%
filter(n > 8) %>%
graph_from_data_frame()
grafica_bigrama## IGRAPH 109b853 DN-- 37 26 --
## + attr: name (v/c), n (e/n)
## + edges from 109b853 (vertex names):
## [1] thy ->soul thou ->art native ->shore suitor ->train
## [5] thy ->care native ->land thy ->native thy ->son
## [9] stranger->guest thy ->mind hast ->thou martial ->maid
## [13] menial ->train shalt ->thou ye ->peers art ->thou
## [17] train ->attends blue ->eyed bridal ->day bridal ->hour
## [21] grace ->divine homeric ->poems native ->shores powers ->divine
## [25] rosy ->wine safe ->return
Mostramos la gráfica de bigramas con más de 10 apariciones
ggplot(conteo_bigramas_unidos,
aes(reorder(bigrama, n),n,fill = reorder(bigrama,-n))) +
geom_bar(stat = 'identity') +
ggtitle("Los bigramas más comunes en La Odisea") +
coord_flip() +
theme(panel.grid.minor = element_blank()) +
xlab(element_blank()) +
ylab(element_blank()) +
scale_fill_viridis(discrete = TRUE, option = "D") +
theme(legend.position = "none")library(readr)
library(stringr)
odisea_sucia <- read_lines("odisea.txt",
skip = 30,
n_max = 15500) # Cargamos una versión del libro en formato ".txt"
odisea_limpia <- character() # Creamos un vector de caracteres
for (i in seq(345, length(odisea_sucia),by = 1)) { # Desde el título "BOOK I"
if (i%%10 == 1) # Si el remanente de la división es igual a 1 prosigue
odisea_limpia[ceiling(i/10)] <- str_c(odisea_sucia[i],
odisea_sucia[i+1],
odisea_sucia[i+2],
odisea_sucia[i+3],
odisea_sucia[i+4],
odisea_sucia[i+5],
odisea_sucia[i+6],
odisea_sucia[i+7],
odisea_sucia[i+8],
odisea_sucia[i+9], sep = " ")
}
odisea_limpia[runif(1,min = 1, max = length(odisea_limpia))]## [1] "ship with lightning and sunk it in mid ocean, so that all his crew were drowned, while he himself was driven by wind and waves on to my island. I got fond of him and cherished him, and had set my heart on making him immortal, so that he should never grow old all his days; still I cannot cross Jove, nor bring his counsels to nothing; therefore, if he insists upon it, let the man go beyond the seas again; but I cannot send him anywhere myself for I have neither ships nor men who can take him. Nevertheless I will readily give him such advice, in all good faith, as will be likely to bring him safely to his own country.” "
library(syuzhet)
odisea_limpia_nrc <- cbind(linea = seq_along(odisea_limpia), get_nrc_sentiment(odisea_limpia))Cambiamos los nombres de los sentimientos obtenidos por el léxico
names(odisea_limpia_nrc) <- c("linea","enfado","anticipación","asco","miedo","alegría","tristeza","sorpresa","confianza","negativo","positivo")Daremos un formato a nuestro vector de sentimientos
# Añadimos el signo negativo a los valores
odisea_limpia_nrc$negativo <- -odisea_limpia_nrc$negativo
# Combinamos las columnas positivo y negativo para crear el "valor" de ambos sentimientos en una sola
nega_posi <- odisea_limpia_nrc %>%
select(linea, positivo, negativo) %>%
melt(id = "linea")
# Renombramos las columnas
names(nega_posi) <- c("linea", "sentimiento", "valor")library(ggthemes)
ggplot(data = nega_posi, aes(x = linea, y = valor, fill = sentimiento)) +
geom_bar(stat = 'identity', position = position_dodge()) + theme_minimal() +
ylab(element_blank()) +
xlab("Número de párrafo") +
ggtitle("Sentimientos Positivos y Negativos en La Odisea")tibble(palabras = 1:length(nega_posi$valor),
Sentimiento = rescale(nega_posi$valor)) %>%
ggplot(aes(palabras, Sentimiento)) +
geom_smooth(se = TRUE,
color = "#00BFC4",
fill = "#00BFC4",
size = 1) +
theme(plot.title = element_text(family = "Helvetica", face = "bold", size = (15))) +
ggtitle("Tendencia suavizada")emociones <- odisea_limpia_nrc %>% select(linea, enfado, anticipación, asco, miedo, alegría, tristeza, sorpresa, confianza) %>% melt(id = "linea")
names(emociones) <- c("número de línea", "sentimiento", "valor")
grupo_emociones <- group_by(emociones, sentimiento)
por_emociones <- summarise(grupo_emociones,
valores=sum(valor))
ggplot(aes(reorder(x=sentimiento, valores), y=valores, fill=reorder(sentimiento,-valores)), data = por_emociones) +
geom_bar(stat = 'identity') + ggtitle("Sentimientos en La Odisea") +
xlab(NULL) +
coord_flip() + theme(legend.position="none") +
scale_fill_viridis(discrete = TRUE, option = "D")